﻿using JuCheap.Core.Infrastructure.Exceptions;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;

namespace JuCheap.Core.Infrastructure.Web
{
    /// <summary>
    /// web api 全局异常日志处理管道
    /// </summary>
    public class WebApiGlobalExceptionMiddleware
    {
        private readonly RequestDelegate next;
        private readonly ILogger<WebApiGlobalExceptionMiddleware> logger;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="next"></param>
        /// <param name="logger"></param>
        public WebApiGlobalExceptionMiddleware(RequestDelegate next, ILogger<WebApiGlobalExceptionMiddleware> logger)
        {
            this.next = next;
            this.logger = logger;
        }

        /// <summary>
        /// invoke
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await next(context);
            }
            catch (Exception ex)
            {
                await WriteExceptionAsync(context, ex).ConfigureAwait(false);
            }
        }

        /// <summary>
        /// 处理异常数据，以及返回数据格式
        /// </summary>
        /// <param name="context"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        private async Task WriteExceptionAsync(HttpContext context, Exception exception)
        {
            var baseException = exception.GetBaseException();
            //记录日志
            logger.LogError(exception, $"异常消息:{baseException.Message}");

            //返回友好的提示
            var response = context.Response;

            //状态码
            var code = 0;
            if (exception is UnauthorizedAccessException)
                code = (int)HttpStatusCode.Unauthorized;
            else if (exception is BusinessException)
                code = (int)HttpStatusCode.BadRequest;
            else if (exception is Exception)
                code = (int)HttpStatusCode.InternalServerError;

            response.ContentType = "application/json";
            response.StatusCode = (int)HttpStatusCode.OK;
            var json = new ResponseJsonData<string>
            {
                Status  = code,
                Message = exception.GetBaseException().Message,
                Result = string.Empty
            };
            var jsonString = JsonSerializer.Serialize(json, JuCheapWebService.GetJuCheapJsonOptions());
            await response.WriteAsync(jsonString).ConfigureAwait(false);
        }
    }
}
